package com.castle.fortress.admin.goods.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.castle.fortress.admin.core.constants.GlobalConstants;
import com.castle.fortress.admin.goods.dto.*;
import com.castle.fortress.admin.goods.entity.*;
import com.castle.fortress.admin.goods.service.*;
import com.castle.fortress.admin.utils.ExcelUtils;
import com.castle.fortress.common.entity.DynamicExcelEntity;
import com.castle.fortress.common.entity.RespBody;
import com.castle.fortress.common.exception.BizException;
import com.castle.fortress.common.respcode.GlobalRespCode;
import com.castle.fortress.common.utils.ConvertUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * 商品表 控制器
 *
 * @author majunjie
 * @since 2021-11-22
 */
@Api(tags = "商品表管理控制器")
@Controller
public class GoodsController {
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private GoodsImgService goodsImgService;
    @Autowired
    private GoodsParamsService goodsParamsService;
    @Autowired
    private GoodsSpecService goodsSpecService;
    @Autowired
    private GoodsSpecItemService goodsSpecItemService;
    @Autowired
    private GoodsOptionService goodsOptionService;

    @ApiOperation("测试接口")
    @GetMapping("/goods/goods/test")
    public void test() {

        GoodsEntity goodsEntity = new GoodsEntity();
        goodsEntity.setId(1234L);
        goodsService.save(goodsEntity);
    }

    /**
     * 商品表的分页展示
     *
     * @param goodsDto 商品表实体类
     * @param current  当前页
     * @param size     每页记录数
     * @return
     */
    @ApiOperation("商品表分页展示")
    @GetMapping("/goods/goods/page")
    @ResponseBody
    @RequiresPermissions("goods:goods:pageList")
    public RespBody<IPage<GoodsDto>> pageGoods(GoodsDto goodsDto, @RequestParam(required = false) Integer current, @RequestParam(required = false) Integer size) {
        Integer pageIndex = current == null ? GlobalConstants.DEFAULT_PAGE_INDEX : current;
        Integer pageSize = size == null ? GlobalConstants.DEFAULT_PAGE_SIZE : size;
        Page<GoodsDto> page = new Page(pageIndex, pageSize);
        IPage<GoodsDto> pages = goodsService.pageGoodsExtends(page, goodsDto);
        pages.getRecords().forEach(dto -> {
            if (StrUtil.isNotEmpty(dto.getImgUrls())) {
                dto.setImgList(Arrays.asList(dto.getImgUrls().split(",")));
            }
        });
        return RespBody.data(pages);
    }

    /**
     * 商品表的列表展示
     *
     * @param goodsDto 商品表实体类
     * @return
     */
    @ApiOperation("商品表列表展示")
    @GetMapping("/goods/goods/list")
    @ResponseBody
    public RespBody<List<GoodsDto>> listGoods(GoodsDto goodsDto) {
        List<GoodsDto> list = goodsService.listGoods(goodsDto);
        return RespBody.data(list);
    }

    /**
     * 商品表保存
     *
     * @param goodsDto 商品表实体类
     * @return
     */
    @ApiOperation("商品表保存")
    @PostMapping("/goods/goods/save")
    @ResponseBody
    @RequiresPermissions("goods:goods:save")
    @Transactional(rollbackFor = Exception.class)
    public RespBody<String> saveGoods(@RequestBody GoodsDto goodsDto) {
        if (goodsDto == null) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        GoodsEntity goodsEntity = ConvertUtil.transformObj(goodsDto, GoodsEntity.class);
        if (goodsService.save(goodsEntity)) {
            goodsDto.setId(goodsEntity.getId());
            // 保存规格等数据
            saveOtherDataList(goodsDto, false);
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 商品表编辑
     *
     * @param goodsDto 商品表实体类
     * @return
     */
    @ApiOperation("商品表编辑")
    @PostMapping("/goods/goods/edit")
    @ResponseBody
    @RequiresPermissions("goods:goods:edit")
    @Transactional(rollbackFor = Exception.class)
    public RespBody<String> updateGoods(@RequestBody GoodsDto goodsDto) {
        if (goodsDto == null || goodsDto.getId() == null || goodsDto.getId().equals(0L)) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        GoodsEntity goodsEntity = ConvertUtil.transformObj(goodsDto, GoodsEntity.class);
        if (goodsService.updateById(goodsEntity)) {
            // 更新参数 规格等数据
            saveOtherDataList(goodsDto, true);
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }


    /**
     * 更新商品的规格、参数等信息
     *
     * @param goodsDto
     * @param isUpdate 是否为修改
     */
    public void saveOtherDataList(GoodsDto goodsDto, Boolean isUpdate) {
        // 若为修改 先删除旧数据
        if (isUpdate) {
            goodsImgService.deleteByGoodsId(goodsDto.getId());
            goodsParamsService.deleteByGoodsId(goodsDto.getId());
            goodsSpecService.deleteByGoodsId(goodsDto.getId());
            goodsSpecItemService.deleteByGoodsId(goodsDto.getId());
            goodsOptionService.deleteByGoodsId(goodsDto.getId());
        }
        // 保存其他图片
        if (goodsDto.getImgList() != null && goodsDto.getImgList().size() > 0) {
            List<GoodsImgEntity> list = new ArrayList<>();
            for (String url : goodsDto.getImgList()) {
                GoodsImgEntity goodsImgEntity = new GoodsImgEntity();
                goodsImgEntity.setImg(url);
                goodsImgEntity.setGoodsId(goodsDto.getId());
                list.add(goodsImgEntity);
            }
            goodsImgService.saveBatch(list);
        }
        // 保存商品参数
        if (goodsDto.getParamsList() != null && goodsDto.getParamsList().size() > 0) {
            int index = 1;
            for (GoodsParamsDto goodsParamsDto : goodsDto.getParamsList()) {
                List<GoodsParamsEntity> list = new ArrayList<>();
                int i = 0;
                if (StrUtil.isNotEmpty(goodsParamsDto.getName()) && StrUtil.isNotEmpty(goodsParamsDto.getValue())) {
                    GoodsParamsEntity goodsParamsEntity = new GoodsParamsEntity();
                    goodsParamsEntity.setGoodsId(goodsDto.getId());
                    goodsParamsEntity.setName(goodsParamsDto.getName());
                    goodsParamsEntity.setValue(goodsParamsDto.getValue());
                    goodsParamsEntity.setSort(i++);
                    list.add(goodsParamsEntity);
                }
                goodsParamsService.saveBatch(list);
                i++;
                goodsParamsDto.setSort(index);
                index++;
            }
        }

        // 保存 规格、规格项目、规格项目详情
        if (goodsDto.getSpecList() != null && goodsDto.getSpecList().size() > 0) {
            goodsDto.getSpecList().forEach(e -> e.setGoodsId(goodsDto.getId()));
            int level = 1;
            for (GoodsSpecDto dto : goodsDto.getSpecList()) {
                dto.setLevel(level++);
            }
            List<GoodsSpecEntity> specEntityList = ConvertUtil.transformObjList(goodsDto.getSpecList(), GoodsSpecEntity.class);
            goodsSpecService.saveBatch(specEntityList);
            List<GoodsSpecItemDto> specItemLists = new ArrayList<>();
            int index = 1;
            for (GoodsSpecEntity goodsSpecEntity : specEntityList) {
                if (goodsSpecEntity.getSpecItemList() != null && goodsSpecEntity.getSpecItemList().size() > 0) {
                    List<GoodsSpecItemDto> specItemList = goodsSpecEntity.getSpecItemList();
                    for (GoodsSpecItemDto goodsSpecItemDto : specItemList) {
                        goodsSpecItemDto.setGoodsId(goodsDto.getId());
                        goodsSpecItemDto.setSpecId(goodsSpecEntity.getId());
                        goodsSpecItemDto.setSort(index++);
                    }
                    specItemLists.addAll(specItemList);
                }
            }
            List<GoodsSpecItemEntity> specItemEntityList = ConvertUtil.transformObjList(specItemLists, GoodsSpecItemEntity.class);
            goodsSpecItemService.saveBatch(specItemEntityList);
            List<String[]> idListList = new ArrayList<>();
            Long specId = specItemEntityList.get(0).getSpecId();
            String[] idArr = {};
            for (GoodsSpecItemEntity goodsSpecItemEntity : specItemEntityList) {
                if (specId.equals(goodsSpecItemEntity.getSpecId())) {
                    idArr = Arrays.copyOf(idArr, idArr.length + 1);
                    idArr[idArr.length - 1] = goodsSpecItemEntity.getId() + "";
                } else {
                    specId = goodsSpecItemEntity.getSpecId();
                    idListList.add(idArr);
                    idArr = new String[]{goodsSpecItemEntity.getId() + ""};
                }
            }
            idListList.add(idArr);
            List resultList = new ArrayList();
            doExchange(idListList, resultList);
            List<GoodsOptionDto> list = goodsDto.getOptionList();

            if(list.size() > 1){
                for (int i = 0; i < list.size(); i++) {
                    List result = (List<String>) resultList.get(0);
                    String spec = result.get(i).toString();
                    spec = spec.substring(1, spec.length() - 1);
                    list.get(i).setSpecs(spec);
                    list.get(i).setGoodsId(goodsDto.getId());
                    list.get(i).setSort(i);
                }
            }else {
                String spec = resultList.get(0).toString();
                spec = spec.substring(1, spec.length() - 1);
                list.get(0).setSpecs(spec);
                list.get(0).setGoodsId(goodsDto.getId());
                list.get(0).setSort(0);
            }

            goodsOptionService.saveBatch(ConvertUtil.transformObjList(list, GoodsOptionEntity.class));
        }
    }

    /**
     * 多个数组值 排列组合
     *
     * @param arrayLists
     * @param resultList
     */
    public void doExchange(List arrayLists, List resultList) {
        int len = arrayLists.size();
        //判断数组size是否小于2，如果小于说明已经递归完成了
        if (len < 2) {
            resultList.addAll(arrayLists);
            return;
//            return arrayLists;
        }
        //拿到第一个数组
        int len0;
        if (arrayLists.get(0) instanceof String[]) {
            String[] arr0 = (String[]) arrayLists.get(0);
            len0 = arr0.length;
        } else {
            len0 = ((ArrayList<String>) arrayLists.get(0)).size();
        }

        //拿到第二个数组
        String[] arr1 = (String[]) arrayLists.get(1);
        int len1 = arr1.length;

        //计算当前两个数组一共能够组成多少个组合
        int lenBoth = len0 * len1;

        //定义临时存放排列数据的集合
        ArrayList<ArrayList<String>> tempArrayLists = new ArrayList<>(lenBoth);

        //第一层for就是循环arrayLists第一个元素的
        for (int i = 0; i < len0; i++) {
            //第二层for就是循环arrayLists第二个元素的
            for (int j = 0; j < len1; j++) {
                //判断第一个元素如果是数组说明，循环才刚开始
                if (arrayLists.get(0) instanceof String[]) {
                    String[] arr0 = (String[]) arrayLists.get(0);
                    ArrayList<String> arr = new ArrayList<>();
                    arr.add(arr0[i]);
                    arr.add(arr1[j]);
                    //把排列数据加到临时的集合中
                    tempArrayLists.add(arr);
                } else {
                    //到这里就明循环了最少一轮啦，我们把上一轮的结果拿出来继续跟arrayLists的下一个元素排列
                    ArrayList<ArrayList<String>> arrtemp = (ArrayList<ArrayList<String>>) arrayLists.get(0);
                    ArrayList<String> arr = new ArrayList<>();
                    for (int k = 0; k < arrtemp.get(i).size(); k++) {
                        arr.add(arrtemp.get(i).get(k));
                    }
                    arr.add(arr1[j]);
                    tempArrayLists.add(arr);
                }
            }
        }

        //这是根据上面排列的结果重新生成的一个集合
        List newArrayLists = new ArrayList<>();
        //把还没排列的数组装进来，看清楚i=2的喔，因为前面两个数组已经完事了，不需要再加进来了
        for (int i = 2; i < arrayLists.size(); i++) {
            newArrayLists.add(arrayLists.get(i));
        }
        //记得把我们辛苦排列的数据加到新集合的第一位喔，不然白忙了
        newArrayLists.add(0, tempArrayLists);

        //你没看错，我们这整个算法用到的就是递归的思想。
        doExchange(newArrayLists, resultList);
    }


    /**
     * 商品表删除
     *
     * @param id
     * @return
     */
    @ApiOperation("商品表删除")
    @PostMapping("/goods/goods/delete")
    @ResponseBody
    @RequiresPermissions("goods:goods:delete")
    public RespBody<String> deleteGoods(@RequestParam Long id) {
        if (id == null) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        if (goodsService.removeById(id)) {
            // 将其他数据删除

            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }


    /**
     * 商品表批量删除
     *
     * @param ids
     * @return
     */
    @ApiOperation("商品表批量删除")
    @PostMapping("/goods/goods/deleteBatch")
    @ResponseBody
    @RequiresPermissions("goods:goods:deleteBatch")
    public RespBody<String> deleteGoodsBatch(@RequestBody List<Long> ids) {
        if (ids == null || ids.size() < 1) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        if (goodsService.removeByIds(ids)) {
            ids.forEach(id->{
                goodsImgService.deleteByGoodsId(id);
                goodsParamsService.deleteByGoodsId(id);
                goodsSpecService.deleteByGoodsId(id);
                goodsSpecItemService.deleteByGoodsId(id);
                goodsOptionService.deleteByGoodsId(id);
            });
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 商品表详情
     *
     * @param id 商品表id
     * @return
     */
    @ApiOperation("商品表详情")
    @GetMapping("/goods/goods/info")
    @ResponseBody
    @RequiresPermissions("goods:goods:info")
    public RespBody<GoodsDto> infoGoods(@RequestParam Long id) {
        if (id == null) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        GoodsDto goodsDto = goodsService.getByIdExtends(id);
        if (StrUtil.isNotEmpty(goodsDto.getImgUrls())) {
            goodsDto.setImgList(Arrays.asList(goodsDto.getImgUrls().split(",")));
        }
        // 查询商品的参数
        goodsDto.setParamsList(goodsParamsService.listByGoodsId(id));
        // 查询商品的规格
        goodsDto.setSpecList(goodsSpecService.listByGoodsId(id));
        // 查询商品规格详情
        goodsDto.setOptionList(goodsOptionService.listByGoodsId(id));
        return RespBody.data(goodsDto);
    }

    /**
     * 动态表头导出 依据展示的字段导出对应报表
     *
     * @param dynamicExcelEntity
     * @param response
     * @throws Exception
     */
    @PostMapping("/goods/goods/exportDynamic")
    @ApiOperation("动态表头导出，依据展示的字段导出对应报表")
    public void exportDynamic(@RequestBody DynamicExcelEntity<GoodsDto> dynamicExcelEntity, HttpServletResponse response) throws Exception {
        List<GoodsDto> list = goodsService.listGoods(dynamicExcelEntity.getDto());
        //字典、枚举、接口、json常量等转义后的列表数据 根据实际情况初始化该对象，null为list数据直接导出
        List<List<Object>> dataList = null;
        /**
         * 根据实际情况初始化dataList,可参照 com.castle.fortress.admin.system.controller.TmpDemoController类中方法：exportDynamic
         */
        ExcelUtils.exportDynamic(response, dynamicExcelEntity.getFileName() + ".xlsx", null, list, dynamicExcelEntity.getHeaderList(), dataList);
    }


}
